//------------------------------------------------------------------------------
// winestore version 15
// author Luo Xu on 2014.08.02
// Tested successfully.
//
// modified by zhangwei on 2014.08.02
// - Add config.base
// - Rename Wine as WineModel in order to distinguish wine object and wine model object.
// - Refactoring the source code.
// modified by zhangwei in 2014.09
// - Refacotored the structure.
// modified by zhangwei on 2014.10.08
// - This version is derived from version 10 directly. The developer revised the 
//   whiole program structure and make it better than ever. Hope it can be a good
//   template for new modules.
// modified by zhangwei on 2014.12.31
// - Revised. Eliminate some old source code. Also simplified some coding.
// modified by zhangwei on 2015.02.13
// - Copied "webapp/winestore-v14*.*" to "webapp/examples/winestore/winestore-v15.*",
//   and upgrade the css, js and rest backend URL with new relative link.
//   This version is the same as v14 except above modifications.
//	 Tested Ok
// - Add reference to "bootstrap.min.js" though it's not mandatory now.
//------------------------------------------------------------------------------

// Save the URL prefix of the current webapp

var config = {
  //base: "api/"
  //base: "mvc/"
  base: "http://openwsn.tongji.edu.cn/site/mvc/"
  //base: "/site/mvc"
};

//------------------------------------------------------------------------------
// Service Layer
// for business logic including data access and network communication. 
//------------------------------------------------------------------------------

window.WineModel = Backbone.Model.extend({
  // you can also uses urlRoot: config.base +　"api/wines". In this way, this 
  // page and js file can be moved into sub folders. 
  urlRoot: config.base + "wines",

  defaults: {
    "id": null,
    "name": "",
    "grapes": "",
    "country": "USA",
    "region": "California",
    "year": "",
    "description": "",
//		"picture" : ""                
  },

  initialize: function () {
    this.bind('validate', function (model, error) {
      alert(error);
    });
  },

  // The returned string will be popup by the browser to notify the user.
  validate: function (attributes) {
    if (attributes.name == '') {
      return "name can't be null";
    }
  }
});

// window.WineCollectionModel = Backbone.Collection.extend({
//	model : WineModel,
//	url : "api/wines"
// });

// modified by luoxu
// The "client" mode means the collection are fully on the client side. 
// The mode should be "client" to enable client side caching for paging.
//
window.PageableWineCollectionModel = Backbone.PageableCollection.extend({
  model: WineModel,
  url: config.base + "wines",
  state: {
    pageSize: 10
  },
  mode: "client"
});

//------------------------------------------------------------------------------
// View Layer
// for user interaction. Including render the data in the models to webpage
// and accepting the page input to model for saving. 
//------------------------------------------------------------------------------

// In order to guarantee releasing resources when view is closed
//
Backbone.View.prototype.close = function () {
  console.log('Closing view ' + this);
  if (this.beforeClose) {
    this.beforeClose();
  }
  this.remove();
  this.unbind();
};

window.WineView = Backbone.View.extend({

  initialize: function () {
    this.template = _.template($('#tpl_itemdetail').html());
    this.model.on("change", this.render, this);
  },

  render: function () {
    $(this.el).html(this.template(this.model.toJSON()));
    return this;
  },

  events: {
    "change input": "onInputChange",
    "click .save": "onSaveWine",
    "click .cancel": "onCancel"
  },

  onInputChange: function (event) {
    var target = event.target;
    console.log('changing ' + target.id + ' from: ' + target.defaultValue + ' to: ' + target.value);
  },

  onSaveWine: function () {
    this.model.set({
      name: $('#name').val(),
      grapes: $('#grapes').val(),
      country: $('#country').val(),
      region: $('#region').val(),
      year: $('#year').val(),
      description: $('#description').val()
    });
    if (!this.model.isValid()) {
      alert("name can't be empty!");
      return false;
    }

    // http://stackoverflow.com/questions/16256635/backbone-model-saving-and-callback-issues
    // The model must belong to the pagable wine list
    this.model.save(null, {
      success: function () {
        alert("save successfully!");
        app.navigate('', {trigger: true});
      },
      error: function (error) {
        console.log("exception encountered when save data");
      }
    });

    return false;
  },

  onCancel: function () {
    app.navigate('', {trigger: true});
  }
});


BackgridColumns = [{
  // enable the select-all extension of the backgrid component
  name: "",
  cell: "select-row",
  headerCell: "select-all"
}, {
  name: "id",
  label: "ID",
  editable: false,
  cell: Backgrid.IntegerCell.extend({
    orderSeparator: ''
  })
}, {
  name: "name",
  label: "Name",
  editable: false,
  cell: Backgrid.StringCell.extend({
    orderSeparator: ''
  })
}, {
  name: "grapes",
  label: "Grapes",
  editable: false,
  cell: Backgrid.StringCell.extend({
    orderSeparator: ''
  })
}, {
  name: "country",
  label: "Country",
  editable: false,
  cell: Backgrid.StringCell.extend({
    orderSeparator: ''
  })
}, {
  name: "region",
  label: "Region",
  editable: false,
  cell: Backgrid.StringCell.extend({
    orderSeparator: ''
  })
}, {
  name: "year",
  label: "Year",
  editable: false,
  cell: Backgrid.StringCell.extend({
    orderSeparator: ''
  })
}, {
  name: "description",
  label: "Description",
  editable: false,
  cell: Backgrid.StringCell.extend({
    orderSeparator: ''
  })
}, {
  name: "delete",
  label: "",
  editable: false,
  cell: Backgrid.Cell.extend({
    template: _.template('<button class="btn btn-danger">Delete</button>'),
    events: {
      "click": "onDeleteRow"
    },
    onDeleteRow: function (e) {
      e.preventDefault();
      this.model.destroy({
        success: function (model, response) {
          alert('Wine deleted successfully ');
        },
        error: function (error) {
          console.log("exception encountered when delete data");
        }
      });
      return false;
    },
    render: function () {
      this.$el.html(this.template());
      this.delegateEvents();
      return this;
    }
  })
}, {
  name: "edit",
  label: "",
  editable: false,
  cell: Backgrid.Cell.extend({
    template: _.template('<a href="#wines/<%= this.model.id %>" class="btn btn-primary">Edit</a>'),
    events: {
      "click": "onEditRow",
    },

    onEditRow: function (e) {
      e.preventDefault();
      //app.navigate("wines/:id", {trigger: true}); 
      app.navigate("wines/" + this.model.id, {trigger: true});
      return false;
    },

    render: function () {
      this.$el.html(this.template());
      this.delegateEvents();
      return this;
    }
  })
}];


// Set up a grid to use the pageable collection
window.WineCollectionView = Backbone.View.extend({

  grid: Backgrid.Grid,

  // The el and model object are passed in when instantiate this object(new this object).
  // model: winelist,

  events: {
    'click #addnew': 'onAddnew',
    'click #deleteselected': 'onDeleteSelected',
  },

  initialize: function () {
    console.log("WineCollectionView initialized!");

    this.template = _.template($("#tpl_itemlist").html());

    /*
     this.model.on("change", this.render, this);
     */

    // this.on("reset", function(collection){
    // 	this.render();
    // });
  },

  render: function () {
    grid = new Backgrid.Grid({
      columns: BackgridColumns,
      collection: this.model
    });

    //$(this.el).html(this.template(this.model.toJSON()));
    $(this.el).html(this.template());

    $("#backgrid").html(grid.render().el);

    var filter = new Backgrid.Extension.ClientSideFilter({
      collection: this.model,
      fields: ['description']
    });
    $("#backgrid").prepend(filter.render().el);
    var paginator = new Backgrid.Extension.Paginator({
      collection: this.model
    });
    $("#backgrid").append(paginator.render().el);

    return this;
  },

  onAddnew: function () {
    console.log("addnew selected click");
    $('#objecteditor').html(new WineView({model: new WineModel()}).render().el);
    app.navigate("wines/", true);
  },

  onDeleteSelected: function () {
    console.log("delete selected click");

    var selectedModels = grid.getSelectedModels();
    if (selectedModels == null) {
      alert("Please select what you want to delete first!");
    }
    else if (selectedModels.length > 5) {
      alert("This application doesn't allow you delete objects more than 5! You could only select at most 5");
    }
    else {
      _.each(selectedModels, function (model) {
        model.destroy({
          success: function (model, response) {
            console.log("delete selected successfully " + model);
          },
          error: function (error) {
            console.log("exception encountered when delete data");
          }
        })
      });
    }
  }
});


// Tile is defined an area containing object list, object detail and their related 
// operations. It's an integration of object collection view and object item view
// together.
//
// TODO
//
window.WineTile = Backbone.View.extend({

  // The el will be passed when instantiate this object.
  // el: $("#winetile"),

  initialize: function () {
    this.template = _.template($("#tpl_winetile").html());

    this.model.fetch({
      success: function (collection, resq, options) {
        console.log('WineTile Fetch successfully.');
      }
    });

  },

  render: function () {
    this.$el.html(this.template());
    var view = new WineCollectionView({el: "#objecteditor", model: this.model});
    view.render();
  },
});


//------------------------------------------------------------------------------
// Controller Definition
//------------------------------------------------------------------------------

var WineStoreApplication = Backbone.Router.extend({

  // Declare the model variable, so that the view and use it later. 
  // winelist = new window.PageableWineCollectionModel();
  winelist: null,

  routes: {
    '': 'getItemList',
    "wines/new": "addNew",
    //"wines/deleteselected" : "deleteSelected",
    "wines/:id": "editItemDetail",
  },

  initialize: function () {
    winelist = new window.PageableWineCollectionModel();
  },

  showView: function (selector, view) {
    $(selector).empty();
    $(selector).html(view.render().el);
    this.currentView = view;
    return view;
  },

  getItemList: function () {
    // attention: I don't know why the backgrid can display data successfully
    // when passing the model here.
    var winetile = new window.WineTile({el: "#winetile", model: winelist});
    winetile.render();

    // attention you cannot call app.showView() because the return value of render()
    // method seems not appropriate.
    //app.showView('#winetile', new WineCollectionView());
  },

  editItemDetail: function (id) {
    var wine = winelist.get(id);
    if (wine == null) {
      alert("editItemDetail: Failed to get the model object! ");
    }
    else {
      app.showView('#objecteditor', new WineView({model: wine}));
    }
    ;
  },

  addNew: function () {
    console.log("router add new");
    $('#objecteditor').html(new WineView({model: new WineModel()}).render().el);
    //app.showView('#objecteditor', new WineView({model : new WineModel()}));
  },
});

$(document).ready(function () {
  app = new WineStoreApplication();
  app.getItemList();
  Backbone.history.start();
});
